﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TicTacToe
{
    enum Difficulty { Normal, Unbeatable};

    class TicTacToe
    {
        char[] Board;
        int choice;
        Difficulty Diff;

        public bool Win(char player)
        {
            //0 1 2
            //3 4 5
            //6 7 8
            //
            //sprawdzenie wszystkich kolumn
            //
            for (int i = 0; i < 3; i++)
            {
                if (Board[i] == player && Board[i + 3] == player && Board[i + 6] == player)
                    return true;
            }
            //
            //sprawdzenie wszystkich wierszy
            //
            for (int i = 0; i < 9; i += 3)
            {
                if (Board[i] == player && Board[i + 1] == player && Board[i + 2] == player)
                    return true;
            }
            //
            //sprawdzenie przekątnych 0-4-8 i 2-4-6
            //
            if (Board[0] == player && Board[4] == player && Board[8] == player)
                return true;
            if (Board[2] == player && Board[4] == player && Board[6] == player)
                return true;
            return false;
        }

        public bool Draw()
        {
            for (int i = 0; i < 9; i++)
            {
                if (Board[i] == '\0') return false;
            }
            return true;
            //
            //w przypadku napotkania "przerwy" - gra jeszcze się nie zakończyła, zwraca false
            //w przeciwnym razie wszystkie pola są wypełnione - zwraca true
            //
        }

        int minimax(char player, int depth)
        {
            if (Win('O')) return 10 - depth;
            else if (Win('X')) return depth - 10;
            else if (Draw()) return 0;
            depth++;

            List<int> scores = new List<int>();
            List<int> moves = new List<int>();
            for (int i = 0; i < 9; i++)
            {
                if (Board[i] == '\0')
                {
                    moves.Add(i);
                    Board[i] = player;
                    if (Diff == Difficulty.Normal && depth > 3) scores.Add(0);
                    else scores.Add(minimax(player == 'O' ? 'X' : 'O', depth));
                    Board[i] = '\0';
                }
            }
            if (player == 'O')
            {
                choice = moves[scores.IndexOf(scores.Max())];
                return scores.Max();
            }
            else
            {
                choice = moves[scores.IndexOf(scores.Min())];
                return scores.Min();
            }
        }

        public int CalculateCPUMove()
        {
            minimax('O', 0);
            Board[choice] = 'O';
            return choice;
        }

        public void PlayerMove(int fieldIndex)
        {
            Board[fieldIndex] = 'X';
        }

        public TicTacToe(Difficulty diff)
        {
            Board = new char[9];
            Diff = diff;
        }

        public override string ToString()
        {
            string result = "";
            for (int i = 0; i < 9; i++)
            {
                if (i % 3 == 0 && i != 0) result += '\n';
                if (Board[i] == '\0') result += "_" + " ";
                else result += Board[i] + " ";
            }
            return result;
        }
    }
}
